/**
 * 文件名   : parconf_cxx.cpp
 * 开发者   : Marco
 * 创建时间 : 2016年5月25日, 上午10:50
 */

#ifndef MARCO_NO_CONF
#ifdef __cplusplus

#include "parconf.h"

#include <stdio.h>
#include <marco/parconf.h>

namespace marco {

/**
 * 配置实现类
 */
class parconf_impl {
public:
    explicit parconf_impl(const char* filename) throw(int) { // 构造并解析
	if (!(handle = parconf_parse(filename))) { throw(1); }
    }
    ~parconf_impl(void) { parconf_destroy(handle); }
    
    pargrp_handle get_group(const char* group_name) { return parconf_get_group(handle, group_name); }
    bool add_group(const char* group_name) { return (bool)parconf_add_group(handle, group_name); }
    bool del_group(const char* group_name) { return (bool)parconf_del_group_by_name(handle, group_name); }
    bool rename_group(const char* group_name, const char* new_name) {
	pargrp_handle group = parconf_get_group(handle, group_name);
	return group ? (bool)parconf_group_rename(group, new_name) : false;
    }
    
    bool add_key(const char* group_name, const char* key, const char* value, bool update) {
	pargrp_handle group = parconf_get_group(handle, group_name);
	return group ? (bool)parconf_group_add(group, key, value, (int)update) : false;
    }
    
    bool del_key(const char* group_name, const char* key) {
	pargrp_handle group = parconf_get_group(handle, group_name);
	return group ? (bool)parconf_group_del(group, key) : false;
    }
    
    bool rename_key(const char* group_name, const char* old_key, const char* new_key) { // 更新键名
	pargrp_handle group = parconf_get_group(handle, group_name);
	return group ? (bool)parconf_group_rename_key(group, old_key, new_key) : false;
    }
    
    bool update_value(const char* group_name, const char* key, const char* value, bool add) { // 更新值
	pargrp_handle group = parconf_get_group(handle, group_name);
	return group ? (bool)parconf_group_update_value(group, key, value, (int)add) : false;
    }
    const char* find(const char* group_name, const char* key) const {	// 群组内根据key查找value
	return parconf_find_with_group(handle, group_name, key);
    }
    
    const char* find(const char* key) const { return parconf_find(handle, key); } // 根据key在所有群组中查找value
    void output(FILE* fp, bool pertty) { parconf_output(handle, fp, (int)pertty); }
    bool output(const char* filename, bool pertty) { return parconf_output_file(handle, filename, pertty); }
    
    friend class pargrp;
private:
    parconf_handle handle;
};

/**
 * 群组实现类
 */
class pargrp_impl {
public:
    friend pargrp;
    explicit pargrp_impl(parconf_handle handle, const char* group_name) throw(int) {
	if (!(group_ = parconf_get_group(handle, group_name))) { throw(1); }
    }
    explicit pargrp_impl(const pargrp_impl& orgi) { // 拷贝构造
	printf("copy pargrp_impl...\n");
	group_ = orgi.group_; // 指针可以共享, 本类不会释放资源
    }
    const char* get_name(void) const { return parconf_group_get_name(group_); }
    bool rename(const char* name) { return (bool)parconf_group_rename(group_, name); }
    const char* find(const char* key) const { return parconf_group_find(group_, key); }
    bool rename_key(const char* old_key, const char* new_key) { return (bool)parconf_group_rename_key(group_, old_key, new_key); }
    bool update_value(const char* key, const char* value, bool add) { return (bool)parconf_group_update_value(group_, key, value, (int)add); }
    bool add(const char* key, const char* value, bool update) { return (bool)parconf_group_add(group_, key, value, (int)update); }
    bool del(const char* key) { return (bool)parconf_group_del(group_, key); }
private:
    pargrp_handle group_;
};

// ------------------------------- 群组对外接口实现
pargrp::pargrp(parconf& conf, const char* group_name) throw(int) {
    if (!conf.valid()) throw (1);
    try { impl = new pargrp_impl(conf.impl->handle, group_name); } 
    catch (int i) { throw (i); } 
}
pargrp::pargrp(const pargrp& orig) {  // 拷贝构造
    printf("copy pargrp...\n");
    impl = new pargrp_impl(*orig.impl);
}
#if (__cplusplus >= 201103L)
pargrp::pargrp(pargrp&& orig) { // 移动构造
    this->impl = orig.impl;
    orig.impl = nullptr;
    printf("move pargrp_impl...\n");
}
#endif
pargrp::~pargrp(void) {	if (impl) delete impl; }
const char* pargrp::get_name(void) const { return impl->get_name(); } // 获取名称
bool pargrp::rename(const char* name) { return impl->rename(name); } // 改名
const char* pargrp::find(const char* key) const { return impl->find(key); } // 查找key
const char* pargrp::operator[] (const char* key) const { return impl->find(key); }
const char* pargrp::operator() (const char* key) const { return impl->find(key); }
bool pargrp::rename_key(const char* old_key, const char* new_key) { return impl->rename_key(old_key, new_key); } // 更新key
bool pargrp::update_value(const char* key, const char* value, bool add) { return impl->update_value(key, value, add); } // 更新value
bool pargrp::add(const char* key, const char* value, bool update) { return impl->add(key, value, update); } // 添加记录
bool pargrp::del(const char* key) { return impl->del(key); } // 删除记录


// ------------------------------- 配置对外接口实现
/**
 * 默认构造, 不会抛出异常 
 */
parconf::parconf(void) throw() : impl(NULL) { }
parconf::parconf(const char* filename) throw(int) {
    try { impl = new parconf_impl(filename); }
    catch (int i) { throw(i); }
}
parconf::~parconf(void) {  if (impl) delete impl; }
bool parconf::valid(void) const { return impl ? true : false; } // 解析是否有效
const char* parconf::find(const char* key) const throw() { return (impl ? impl->find(key) : NULL); } // 所有群组中查找key
const char* parconf::find(const char* group_name, const char* key) const throw() { return (impl ? impl->find(group_name, key) : NULL); } // 指定群组中查找key
const char* parconf::operator [](const char* key) const { return (impl ? impl->find(key) : NULL); } // 运算符重载, 根据key查找value
const char* parconf::operator ()(const char* key) const { return (impl ? impl->find(key) : NULL); }
const char* parconf::operator() (const char* group_name, const char* key) const { return (impl ? impl->find(group_name, key) : NULL); } // 运算符重载, 在指定群组中, 根据key查找value
bool parconf::add_group(const char* group_name) { return impl ? impl->add_group(group_name) : false; } // 添加群组
bool parconf::del_group(const char* group_name) { return impl ? impl->del_group(group_name) : false; } // 删除群组1
bool parconf::del_group(const pargrp& group) { return impl ? impl->del_group(group.get_name()) : false; } // 删除群组2
bool parconf::rename_group(const char* group_name, const char* new_name) { 
    return (impl ? impl->rename_group(group_name, new_name) : false); 
}
bool parconf::add_key(const char* group_name, const char* key, const char* value, bool update) {
    return (impl ? impl->add_key(group_name, key, value, update) : false);
}
bool parconf::del_key(const char* group_name, const char* key) {
    return (impl ? impl->del_key(group_name, key) : false);
}
bool parconf::rename_key(const char* group_name, const char* old_key, const char* new_key) {
    return (impl ? impl->rename_key(group_name, old_key, new_key) : false);
}
bool parconf::update_value(const char* group_name, const char* key, const char* value, bool add) {
    return (impl ? impl->update_value(group_name, key, value, add) : false);
}
void parconf::output(FILE* fp, bool pertty) { if (impl) impl->output(fp, pertty); } // 输出到流
bool parconf::output(const char* filename, bool pertty) { return (impl ? impl->output(filename, pertty) : false); } // 输出到文件路径

pargrp parconf::get_group(const char* group_name) throw (int) { // 获取群组
    if (!impl) throw (1);
    try { return pargrp(*this, group_name); }
    catch (int i) { throw (i); }
} 

bool parconf::parse(const char* filename) throw() { // 解析文件
    if (impl) delete impl;  // 之前已解析过
    try { impl = new parconf_impl(filename); return true;
    } catch(int i) { impl = NULL; return false; }
}


}   // namespace marco
#endif	// __cplusplus
#endif // MARCO_NO_CONF